#ifndef __SERVLET_H__
#define __SERVLET_H__

#include <memory>
#include <functional>
#include <string>
#include <vector>
#include <unordered_map>
#include "http.h"
#include "http_session.h"
#include "thread.h"
#include "util.h"

namespace johnsonli
{
namespace http
{
    class Servlet
    {
    public:
        typedef std::shared_ptr<Servlet> ptr;

        Servlet(const std::string& name)
            :m_name(name) {}

        virtual ~Servlet() {}

        /**
         * @brief 处理请求
         * @param[in] request HTTP请求
         * @param[in] response HTTP响应
         * @param[in] session HTTP连接
         * @return 是否处理成功
         */
        virtual int32_t handle(johnsonli::http::HttpRequest::ptr request
                    , johnsonli::http::HttpResponse::ptr response
                    , johnsonli::http::HttpSession::ptr session) = 0;

        const std::string& getName() const { return m_name;}
    
    protected:
        std::string m_name;     // servlet名称
    };

    /**
    * @brief 函数式Servlet
    */
    class FunctionServlet : public Servlet {
    public:
        /// 智能指针类型定义
        typedef std::shared_ptr<FunctionServlet> ptr;
        
        /// 函数回调类型定义
        typedef std::function<int32_t (johnsonli::http::HttpRequest::ptr request
                    , johnsonli::http::HttpResponse::ptr response
                    , johnsonli::http::HttpSession::ptr session)> callback;


        /**
         * @brief 构造函数
         * @param[in] cb 回调函数
         */
        FunctionServlet(callback cb);

        virtual int32_t handle(johnsonli::http::HttpRequest::ptr request
                    , johnsonli::http::HttpResponse::ptr response
                    , johnsonli::http::HttpSession::ptr session) override;
    private:
        /// 回调函数
        callback m_cb;
    };


    /**
     * @brief Servlet分发器
     */
    class ServletDispatch : public Servlet 
    {
    public:
        typedef std::shared_ptr<ServletDispatch> ptr;
        typedef RWMutex RWMutexType;

        ServletDispatch(const std::string& servername);

        virtual int32_t handle(johnsonli::http::HttpRequest::ptr request
                   , johnsonli::http::HttpResponse::ptr response
                   , johnsonli::http::HttpSession::ptr session) override;

         /**
         * @brief 添加servlet
         * @param[in] uri uri
         * @param[in] slt serlvet
         */
        void addServlet(const std::string& uri, Servlet::ptr slt);

        /**
         * @brief 添加servlet
         * @param[in] uri uri
         * @param[in] cb FunctionServlet回调函数
         */
        void addServlet(const std::string& uri, FunctionServlet::callback cb);

        /**
         * @brief 添加模糊匹配servlet
         * @param[in] uri uri 模糊匹配 /sylar_*
         * @param[in] slt servlet
         */
        void addGlobServlet(const std::string& uri, Servlet::ptr slt);

        /**
         * @brief 添加模糊匹配servlet
         * @param[in] uri uri 模糊匹配 /sylar_*
         * @param[in] cb FunctionServlet回调函数
         */
        void addGlobServlet(const std::string& uri, FunctionServlet::callback cb);

        /**
         * @brief 删除servlet
         * @param[in] uri uri
         */
        void delServlet(const std::string& uri);

        /**
         * @brief 删除模糊匹配servlet
         * @param[in] uri uri
         */
        void delGlobServlet(const std::string& uri);

        /**
         * @brief 返回默认servlet
         */
        Servlet::ptr getDefault() const { return m_default;}

        /**
         * @brief 设置默认servlet
         * @param[in] v servlet
         */
        void setDefault(Servlet::ptr v) { m_default = v;}


        /**
         * @brief 通过uri获取servlet
         * @param[in] uri uri
         * @return 返回对应的servlet
         */
        Servlet::ptr getServlet(const std::string& uri);

        /**
         * @brief 通过uri获取模糊匹配servlet
         * @param[in] uri uri
         * @return 返回对应的servlet
         */
        Servlet::ptr getGlobServlet(const std::string& uri);

        /**
         * @brief 通过uri获取servlet
         * @param[in] uri uri
         * @return 优先精准匹配,其次模糊匹配,最后返回默认
         */
        Servlet::ptr getMatchedServlet(const std::string& uri);

    private:
        /// 读写互斥量
        RWMutexType m_mutex;
        /// 精准匹配servlet MAP
        /// uri(/sylar/xxx) -> servlet
        std::unordered_map<std::string, Servlet::ptr> m_datas;
        /// 模糊匹配servlet 数组
        /// uri(/sylar/*) -> servlet
        std::vector<std::pair<std::string, Servlet::ptr>> m_globs;
        /// 默认servlet，所有路径都没匹配到时使用
        Servlet::ptr m_default;

        std::string m_servername;
    };


    /**
     * @brief NotFoundServlet(默认返回404)
     */
    class NotFoundServlet : public Servlet 
    {
    public:
        typedef std::shared_ptr<NotFoundServlet> ptr;

        NotFoundServlet(const std::string& name);

        virtual int32_t handle(johnsonli::http::HttpRequest::ptr request
                    , johnsonli::http::HttpResponse::ptr response
                    , johnsonli::http::HttpSession::ptr session) override;

    private:
        std::string m_name;
        std::string m_content;
    };


    class ReSourseServlet : public Servlet
    {
    public:
        ReSourseServlet(const std::string& path);

        virtual int32_t handle(johnsonli::http::HttpRequest::ptr request
                    , johnsonli::http::HttpResponse::ptr response
                    , johnsonli::http::HttpSession::ptr session) override;

    private:
        std::string m_path;
    };

}
}    

#endif